import { Component, OnInit, Input } from '@angular/core';
import { FormGroup, FormBuilder, AbstractControl, FormControl, Validators, FormArray } from '@angular/forms';
import { NzModalSubject } from 'ng-zorro-antd';

import { QueryRuleOperator, QueryRuleResult } from '../properties-query.model';
import { operatorsForNumber, operatorsForString } from '../query-rule-operators';
import { FeaturePropertyType, PropertyTypes } from '../../../models/layer.model';

@Component({
  selector: 'ege-properties-query',
  templateUrl: './properties-query.component.html',
  styleUrls: ['./properties-query.component.scss']
})
export class PropertiesQueryComponent implements OnInit {

  private _fields: FeaturePropertyType[];
  private _initial: QueryRuleResult;

  loading: boolean = false;
  dynaactionform: FormGroup;
  
  @Input()
  set fields(value: FeaturePropertyType[]) {
    this._fields = value;
  }

  get fields(): FeaturePropertyType[] {
    return this._fields;
  }

  @Input()
  set initial(value: QueryRuleResult) {
    this._initial = value;
  }

  get initial(): QueryRuleResult {
    return this._initial;
  }

  constructor(
    private fb: FormBuilder,
    private modalSubject: NzModalSubject
  ) { }

  ngOnInit() {
    this.initQueryRuleBuiler();
  }

  private initQueryRuleBuiler(): void {
    this.dynaactionform = this.fb.group({
      operator: ['AND'],
      rules: this.fb.array([])
    });
    if(this.initial) {
      const operatorValue = this.initial.operator;
      const rules = this.initial.rules;
      this.dynaactionform.controls['operator'].setValue(operatorValue);
      rules.forEach(rule => this.addQueryRule(rule));
    } else {
      this.addQueryRule();
    }
  }

  addQueryRule(data = {}): void {
    let values = { field: '', operator: 'equal', value: '', ...data };
    const rules = <FormArray>this.dynaactionform.controls['rules'];
    const field = new FormControl(values.field, Validators.required);
    const operator = new FormControl(values.operator, Validators.required);
    const value = new FormControl(values.value, Validators.required);
    const rule = this.fb.group({ field, operator, value });
    if(values.field === '') {
      operator.disable();
      value.disable();
    } else {
      operator.enable();
      if(values.operator === 'empty' || values.operator === 'notEmpty') {
        value.disable();
      } else {
        value.enable();
      }
    }
    field.valueChanges.subscribe(data => {
      if(data !== values.field) {
        operator.enable();
        operator.setValue('equal');
        value.enable();
        value.setValue('');
      }
      values.field = data;
    });
    operator.valueChanges.subscribe(data => {
      if(data === 'empty' || data === 'notEmpty') {
        value.disable();
      } else {
        value.enable();
      }
      values.operator = data;
    });
    rules.push(rule);
  }

  removeQueryRule(index: number): void {
    const rules = <FormArray>this.dynaactionform.controls['rules'];
    rules.removeAt(index);
  }

  private formatOperators(index: number): QueryRuleOperator[] {
    const rules = <FormArray>this.dynaactionform.controls['rules'];
    const formGroup = <FormGroup>rules.at(index);
    const values = formGroup.value;
    let queryRuleOperator: QueryRuleOperator[] = [];
    if(values && values['field']) {
      const field = this.fields.find(field => field.name === values['field']);
      if(field) {
        queryRuleOperator = this.selectOperator(field.type);
      }
    }
    return queryRuleOperator;
  }

  private selectOperator(type: PropertyTypes): QueryRuleOperator[] {
    switch(type) {
      case PropertyTypes.DateTime:
      case PropertyTypes.Number: {
        return operatorsForNumber;
      }
      case PropertyTypes.String: {
        return operatorsForString;
      }
      default: {
        return [];
      }
    }
  }

  private getFieldType(fieldName: string): PropertyTypes {
    const field = this.fields.find(field => field.name === fieldName);
    return field.type;
  }

  handleConform(): void {
    this.loading = true;
    this.modalSubject.next(this.dynaactionform.value);
  }

  handleCancel(): void {
    this.modalSubject.destroy('onCancel');
  }

  getControls(): any {
    const formGroup: FormGroup = <FormGroup>this.dynaactionform.controls.rules;
    return formGroup.controls;
  }

}
